package org.lex.pci.ch02.similarity;

import java.util.List;

import org.lex.pci.ch02.data.Preferences;
import org.lex.pci.ch02.data.Preferences.Rate;

/**
 * 皮尔逊相关度
 */
public class PearsonSimilarityAlgorithm implements SimilarityAlgorithm {

	@Override
	public String getName() {
		return "Pearson Similarity";
	}

	@Override
	public double getSimilarity(Preferences prefs, String person1, String person2) {
		double result = 0;
		List<Rate[]> shared = prefs.getSharedRate(person1, person2);
		if (null == shared || true == shared.isEmpty()) {
			result = 1;
		} else {
			// 相同偏好之和
			double sum1 = 0;
			double sum2 = 0;
			// 相同偏好平方之和
			double sumSq1 = 0;
			double sumSq2 = 0;
			// 相同偏好乘积之和
			double pSum = 0;

			for (Rate[] r : shared) {
				Rate r1 = r[0];
				Rate r2 = r[1];

				sum1 += r1.getRate();
				sum2 += r2.getRate();

				sumSq1 += Math.pow(r1.getRate(), 2);
				sumSq2 += Math.pow(r2.getRate(), 2);

				pSum += r1.getRate() * r2.getRate();
			}

			// 计算pearson相关度
			int sharedCount = shared.size();
			double den = Math.sqrt((sumSq1 - Math.pow(sum1, 2) / sharedCount)
					* (sumSq2 - Math.pow(sum2, 2) / sharedCount));
			if (0 == den) {
				result = 0;
			} else {
				double num = pSum - (sum1 * sum2 / sharedCount);
				result = num / den;
			}
		}
		return result;
	}

}
